//! 插件机制实现

use std::collections::HashMap;
use std::path::Path;
use serde_json::Value;
use crate::error::{DataForgeError, Result};
use super::{CustomGenerator, ParamType};

/// 插件管理器
pub struct PluginManager {
    plugins: HashMap<String, Box<dyn Plugin>>,
    loaded_paths: Vec<String>,
}

impl PluginManager {
    /// 创建新的插件管理器
    pub fn new() -> Self {
        Self {
            plugins: HashMap::new(),
            loaded_paths: Vec::new(),
        }
    }

    /// 加载插件
    pub fn load_plugin<P>(&mut self, plugin: P) -> Result<()>
    where
        P: Plugin + 'static,
    {
        let name = plugin.name().to_string();
        
        if self.plugins.contains_key(&name) {
            return Err(DataForgeError::validation(&format!(
                "Plugin '{}' is already loaded", name
            )));
        }

        // 初始化插件
        plugin.initialize()?;
        
        self.plugins.insert(name, Box::new(plugin));
        Ok(())
    }

    /// 卸载插件
    pub fn unload_plugin(&mut self, name: &str) -> Result<()> {
        if let Some(mut plugin) = self.plugins.remove(name) {
            plugin.cleanup()?;
            Ok(())
        } else {
            Err(DataForgeError::validation(&format!("Plugin '{}' not found", name)))
        }
    }

    /// 获取插件
    pub fn get_plugin(&self, name: &str) -> Option<&dyn Plugin> {
        self.plugins.get(name).map(|p| p.as_ref())
    }

    /// 列出所有插件
    pub fn list_plugins(&self) -> Vec<PluginInfo> {
        self.plugins.iter().map(|(name, plugin)| {
            PluginInfo {
                name: name.clone(),
                version: plugin.version().to_string(),
                description: plugin.description().to_string(),
                author: plugin.author().to_string(),
                generators: plugin.generators().iter().map(|g| g.name().to_string()).collect(),
            }
        }).collect()
    }

    /// 从目录加载插件
    pub fn load_plugins_from_directory<P: AsRef<Path>>(&mut self, dir: P) -> Result<Vec<String>> {
        let dir_path = dir.as_ref();
        if !dir_path.exists() || !dir_path.is_dir() {
            return Err(DataForgeError::validation("Plugin directory does not exist or is not a directory"));
        }

        let mut loaded_plugins = Vec::new();
        
        // 这里应该实现动态库加载逻辑
        // 由于Rust的动态库加载比较复杂，这里提供一个框架
        // 实际实现需要使用libloading或类似的crate
        
        // 示例：扫描目录中的插件配置文件
        for entry in std::fs::read_dir(dir_path)? {
            let entry = entry?;
            let path = entry.path();
            
            if path.extension().and_then(|s| s.to_str()) == Some("plugin") {
                // 这里应该加载插件配置并实例化插件
                // 目前只是记录路径
                if let Some(path_str) = path.to_str() {
                    self.loaded_paths.push(path_str.to_string());
                    loaded_plugins.push(path_str.to_string());
                }
            }
        }

        Ok(loaded_plugins)
    }

    /// 重新加载所有插件
    pub fn reload_all(&mut self) -> Result<()> {
        // 卸载所有插件
        let plugin_names: Vec<String> = self.plugins.keys().cloned().collect();
        for name in plugin_names {
            self.unload_plugin(&name)?;
        }

        // 重新加载
        let paths = self.loaded_paths.clone();
        for path in paths {
            // 这里应该重新加载插件
            // 目前只是占位符
            println!("Reloading plugin from: {}", path);
        }

        Ok(())
    }

    /// 获取所有生成器
    pub fn get_all_generators(&self) -> Vec<&dyn CustomGenerator> {
        let mut generators = Vec::new();
        
        for plugin in self.plugins.values() {
            generators.extend(plugin.generators());
        }
        
        generators
    }
}

impl Default for PluginManager {
    fn default() -> Self {
        Self::new()
    }
}

/// 插件特征
pub trait Plugin: Send + Sync {
    /// 插件名称
    fn name(&self) -> &str;
    
    /// 插件版本
    fn version(&self) -> &str;
    
    /// 插件描述
    fn description(&self) -> &str;
    
    /// 插件作者
    fn author(&self) -> &str;
    
    /// 初始化插件
    fn initialize(&self) -> Result<()> {
        Ok(())
    }
    
    /// 清理插件
    fn cleanup(&mut self) -> Result<()> {
        Ok(())
    }
    
    /// 获取插件提供的生成器
    fn generators(&self) -> Vec<&dyn CustomGenerator>;
    
    /// 插件配置
    fn config(&self) -> HashMap<String, Value> {
        HashMap::new()
    }
    
    /// 设置插件配置
    fn set_config(&mut self, config: HashMap<String, Value>) -> Result<()> {
        let _ = config;
        Ok(())
    }
}

/// 插件信息
#[derive(Debug, Clone)]
pub struct PluginInfo {
    pub name: String,
    pub version: String,
    pub description: String,
    pub author: String,
    pub generators: Vec<String>,
}

/// 示例插件：数学生成器插件
pub struct MathGeneratorPlugin {
    name: String,
    version: String,
    generators: Vec<Box<dyn CustomGenerator>>,
}

impl MathGeneratorPlugin {
    pub fn new() -> Self {
        let mut plugin = Self {
            name: "math_generators".to_string(),
            version: "1.0.0".to_string(),
            generators: Vec::new(),
        };
        
        // 添加数学相关的生成器
        plugin.generators.push(Box::new(RandomNumberGenerator::new()));
        plugin.generators.push(Box::new(MathExpressionGenerator::new()));
        
        plugin
    }
}

impl Plugin for MathGeneratorPlugin {
    fn name(&self) -> &str {
        &self.name
    }

    fn version(&self) -> &str {
        &self.version
    }

    fn description(&self) -> &str {
        "Provides mathematical data generators"
    }

    fn author(&self) -> &str {
        "DataForge Team"
    }

    fn generators(&self) -> Vec<&dyn CustomGenerator> {
        self.generators.iter().map(|g| g.as_ref()).collect()
    }
}

impl Default for MathGeneratorPlugin {
    fn default() -> Self {
        Self::new()
    }
}

/// 随机数生成器
struct RandomNumberGenerator {
    name: String,
}

impl RandomNumberGenerator {
    fn new() -> Self {
        Self {
            name: "random_number".to_string(),
        }
    }
}

impl CustomGenerator for RandomNumberGenerator {
    fn name(&self) -> &str {
        &self.name
    }

    fn description(&self) -> &str {
        "Generates random numbers within specified range"
    }

    fn generate(&self) -> Result<Value> {
        use rand::Rng;
        let mut rng = rand::thread_rng();
        let number = rng.gen_range(0..=100);
        Ok(Value::Number(serde_json::Number::from(number)))
    }

    fn generate_with_params(&self, params: &HashMap<String, Value>) -> Result<Value> {
        use rand::Rng;
        let mut rng = rand::thread_rng();
        
        let min = params.get("min")
            .and_then(|v| v.as_i64())
            .unwrap_or(0);
            
        let max = params.get("max")
            .and_then(|v| v.as_i64())
            .unwrap_or(100);
            
        if min >= max {
            return Err(DataForgeError::validation("Min must be less than max"));
        }
        
        let number = rng.gen_range(min..=max);
        Ok(Value::Number(serde_json::Number::from(number)))
    }

    fn validate_params(&self, params: &HashMap<String, Value>) -> Result<()> {
        if let (Some(min), Some(max)) = (params.get("min"), params.get("max")) {
            if let (Some(min_val), Some(max_val)) = (min.as_i64(), max.as_i64()) {
                if min_val >= max_val {
                    return Err(DataForgeError::validation("Min must be less than max"));
                }
            }
        }
        Ok(())
    }

    fn param_schema(&self) -> HashMap<String, ParamType> {
        let mut schema = HashMap::new();
        schema.insert("min".to_string(), ParamType::Integer { min: None, max: None });
        schema.insert("max".to_string(), ParamType::Integer { min: None, max: None });
        schema
    }
}

/// 数学表达式生成器
struct MathExpressionGenerator {
    name: String,
}

impl MathExpressionGenerator {
    fn new() -> Self {
        Self {
            name: "math_expression".to_string(),
        }
    }
}

impl CustomGenerator for MathExpressionGenerator {
    fn name(&self) -> &str {
        &self.name
    }

    fn description(&self) -> &str {
        "Generates simple mathematical expressions"
    }

    fn generate(&self) -> Result<Value> {
        use rand::Rng;
        let mut rng = rand::thread_rng();
        
        let a = rng.gen_range(1..=100);
        let b = rng.gen_range(1..=100);
        let operators = ["+", "-", "*", "/"];
        let op = operators[rng.gen_range(0..operators.len())];
        
        let expression = format!("{} {} {}", a, op, b);
        Ok(Value::String(expression))
    }

    fn generate_with_params(&self, params: &HashMap<String, Value>) -> Result<Value> {
        use rand::Rng;
        let mut rng = rand::thread_rng();
        
        let max_value = params.get("max_value")
            .and_then(|v| v.as_u64())
            .unwrap_or(100) as i32;
            
        let operators = if let Some(Value::Array(ops)) = params.get("operators") {
            ops.iter()
                .filter_map(|v| v.as_str())
                .collect::<Vec<_>>()
        } else {
            vec!["+", "-", "*", "/"]
        };
        
        if operators.is_empty() {
            return Err(DataForgeError::validation("At least one operator must be specified"));
        }
        
        let a = rng.gen_range(1..=max_value);
        let b = rng.gen_range(1..=max_value);
        let op = operators[rng.gen_range(0..operators.len())];
        
        let expression = format!("{} {} {}", a, op, b);
        Ok(Value::String(expression))
    }

    fn param_schema(&self) -> HashMap<String, ParamType> {
        let mut schema = HashMap::new();
        schema.insert("max_value".to_string(), ParamType::Integer { min: Some(1), max: Some(10000) });
        schema.insert("operators".to_string(), ParamType::Array(Box::new(ParamType::String { max_length: Some(1) })));
        schema
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_plugin_manager() {
        let mut manager = PluginManager::new();
        let plugin = MathGeneratorPlugin::new();
        
        assert!(manager.load_plugin(plugin).is_ok());
        
        let plugins = manager.list_plugins();
        assert_eq!(plugins.len(), 1);
        assert_eq!(plugins[0].name, "math_generators");
        
        let generators = manager.get_all_generators();
        assert_eq!(generators.len(), 2);
    }

    #[test]
    fn test_math_plugin() {
        let plugin = MathGeneratorPlugin::new();
        
        assert_eq!(plugin.name(), "math_generators");
        assert_eq!(plugin.version(), "1.0.0");
        assert!(!plugin.description().is_empty());
        
        let generators = plugin.generators();
        assert_eq!(generators.len(), 2);
    }

    #[test]
    fn test_random_number_generator() {
        let generator = RandomNumberGenerator::new();
        
        let result = generator.generate();
        assert!(result.is_ok());
        
        if let Ok(Value::Number(n)) = result {
            let val = n.as_i64().unwrap();
            assert!(val >= 0 && val <= 100);
        }
        
        let mut params = HashMap::new();
        params.insert("min".to_string(), Value::Number(serde_json::Number::from(10)));
        params.insert("max".to_string(), Value::Number(serde_json::Number::from(20)));
        
        let result = generator.generate_with_params(&params);
        assert!(result.is_ok());
        
        if let Ok(Value::Number(n)) = result {
            let val = n.as_i64().unwrap();
            assert!(val >= 10 && val <= 20);
        }
    }

    #[test]
    fn test_math_expression_generator() {
        let generator = MathExpressionGenerator::new();
        
        let result = generator.generate();
        assert!(result.is_ok());
        
        if let Ok(Value::String(expr)) = result {
            assert!(expr.contains(' '));
            assert!(expr.chars().any(|c| "+-*/".contains(c)));
        }
    }

    #[test]
    fn test_plugin_unload() {
        let mut manager = PluginManager::new();
        let plugin = MathGeneratorPlugin::new();
        
        manager.load_plugin(plugin).unwrap();
        assert_eq!(manager.list_plugins().len(), 1);
        
        assert!(manager.unload_plugin("math_generators").is_ok());
        assert_eq!(manager.list_plugins().len(), 0);
        
        assert!(manager.unload_plugin("nonexistent").is_err());
    }
}